package com.shrw.duke.serialport.shengbenserial.runnable;


public abstract class MyRunnable implements Runnable {

    public static final String STATE_NEW = "New";
    public static final String STATE_PAUSED = "Paused";
    public static final String STATE_RUNNING = "Running";
    public static final String STATE_FINISHED = "Finished";
    private volatile String state = STATE_NEW;
    private volatile boolean workDone = false;
    private volatile boolean pauseWork = false;
    private Thread workerThread;
    private int time;

    protected MyRunnable(int parmTime) {
        time = parmTime;
    }

    private void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return this.state;
    }

    public void pause() {
        this.pauseWork = true;
    }

    public void resume() {
        this.pauseWork = false;
        if (workerThread != null)
            workerThread.interrupt(); //wakeup if sleeping  
    }

    /**
     * startImmediately = true to begin work right away, false = start Work in paused state, call resume() to do work
     */
    public void start(boolean startImmediately) {
        this.pauseWork = !startImmediately;
        workerThread = new Thread(this);
        workerThread.setPriority(Thread.MIN_PRIORITY);
//        workerThread.setDaemon(true);
        workerThread.start();
    }

    public void stop() {
        workDone = true;
        workerThread = null;
    }

    @Override
    public void run() {
        try {
            workDone = false;
            while (!workDone) {
                while (pauseWork) {
                    setState(STATE_PAUSED);
                    try {
                        Thread.sleep(time); //stop for 100ms increments
                    } catch (InterruptedException ie) {
                    }
                }
                setState(STATE_RUNNING);
                doUnitOfWork();
            }
            setState(STATE_FINISHED);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    protected abstract void doUnitOfWork();
}
